#include <stdio.h>

#include "MQTTClient.h"

#include "hi_ext_util.h"
#include "plug_mqtt.h"
#include "plug_mqtt_analysis.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#define ADDRESS     "tcp://192.168.31.217:1883"
#define TIMEOUT     10000L//连接超时
#define USERNAME    "admin"
#define PASSWORD    "admin"
#define CLIENTID    "plug_ipc" //客户端ID

typedef struct tagMQTT_CTX {
    HI_BOOL bConnected;
    HI_CHAR azDeviceID[PLUG_MQTT_MAX_DEVICE_ID_LEN];
    HI_CHAR azMqttAddress[PLUG_MQTT_MAX_DEVICE_ID_LEN];

    HI_CHAR azUserId[PLUG_MQTT_MAX_DEVICE_ID_LEN];
    HI_CHAR azPassword[PLUG_MQTT_MAX_DEVICE_ID_LEN];
} PLUG_MQTT_CTX;


static PLUG_MQTT_CTX s_stMqttCtx = {0};

volatile MQTTClient_deliveryToken deliveredtoken;

static MQTTClient client;
static MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
static MQTTClient_message pubmsg = MQTTClient_message_initializer;
static MQTTClient_deliveryToken token;

/* 确定消息是否成功操作 */
HI_VOID umdelivered(HI_VOID *context, MQTTClient_deliveryToken dt)
{
    LOGD("Message with token value %d delivery confirmed\n", dt);
    deliveredtoken = dt;
}
/* 消息到达时操作 */
HI_S32 ummsgarrvd(HI_VOID *context, HI_S8 *topicName, HI_S32 topicLen, MQTTClient_message *message)
{
    HI_S32 i;
    HI_U8* payloadptr;
    HI_U32* p_type;
    HI_U32 type,ret;
    
    payloadptr = message->payload;
    
    LOGI("Message arrived\n");
    LOGI("topic: %s\n", topicName);
    //LOGI("message length:%d\n",message->payloadlen);    
    //LOGD("message:");

    //解析协议
    ret = PLUG_MQTT_Analysis(payloadptr,message,topicName);
    if(ret != HI_SUCCESS){
        LOGE("[%s,%d]\n",__FUNCTION__,__LINE__);
        return HI_FAILURE;
    }

    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    
    return HI_TRUE;
}
/* 失去连接 */
HI_VOID umconnlost(HI_VOID *context, HI_S8 *cause)
{
    PLUG_MQTT_Connect();
}

HI_S32 PLUG_MQTT_Connect(HI_VOID)
{
    PLUG_COMMON_DEV_INFO_S stInfo = {0};
    HI_S32 s32Ret;
    
    s32Ret = PLUG_COMMON_GetDeviceInfo(&stInfo);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("PLUG_COMMON_GetDeviceInfo error!\n");
        return HI_FAILURE;
    }
    
    snprintf(s_stMqttCtx.azDeviceID, PLUG_MQTT_MAX_DEVICE_ID_LEN, "%s", stInfo.azDeviceId);
    if (strlen(s_stMqttCtx.azDeviceID) <= 0)
    {
        snprintf(s_stMqttCtx.azDeviceID, sizeof(s_stMqttCtx.azDeviceID), "%s", CLIENTID);
    }
    snprintf(s_stMqttCtx.azMqttAddress, PLUG_MQTT_MAX_DEVICE_ID_LEN, "%s", stInfo.azMqttAddress);
    if (strlen(s_stMqttCtx.azMqttAddress) <= 0)
    {
        snprintf(s_stMqttCtx.azMqttAddress, sizeof(s_stMqttCtx.azMqttAddress), "%s", ADDRESS);
    }
    snprintf(s_stMqttCtx.azUserId, PLUG_MQTT_MAX_DEVICE_ID_LEN, "%s", stInfo.azUserId);
    if (strlen(s_stMqttCtx.azUserId) <= 0)
    {
        snprintf(s_stMqttCtx.azUserId, sizeof(s_stMqttCtx.azUserId), "%s", USERNAME);
    }
    snprintf(s_stMqttCtx.azPassword, PLUG_MQTT_MAX_DEVICE_ID_LEN, "%s", stInfo.azPassword);
    if (strlen(s_stMqttCtx.azPassword) <= 0)
    {
        snprintf(s_stMqttCtx.azPassword, sizeof(s_stMqttCtx.azPassword), "%s", PASSWORD);
    }

    MQTTClient_create(&client, s_stMqttCtx.azMqttAddress, s_stMqttCtx.azDeviceID,MQTTCLIENT_PERSISTENCE_NONE, NULL);
    conn_opts.keepAliveInterval = 2;
    conn_opts.cleansession = 1;
    conn_opts.username = s_stMqttCtx.azUserId;
    conn_opts.password = s_stMqttCtx.azPassword;
    
    MQTTClient_setCallbacks(client, NULL, umconnlost, ummsgarrvd, umdelivered);
    if ((s32Ret = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        LOGE("Failed to connect, return code %d\n", s32Ret);
        return HI_FAILURE;
    }
    
    s_stMqttCtx.bConnected = HI_TRUE;
    
    //这条连接需要一直保持着，所以不断开，一条连接实现发布和订阅
    
    return HI_SUCCESS;
}
/* 发送主题 */
HI_S32 PLUG_MQTT_PubClient(const HI_S8* topic,HI_S8 *payload,HI_S32 qos,HI_BOOL retained)
{
    HI_S32 s32Ret;
    
    pubmsg.payload = payload;//消息载体
    pubmsg.payloadlen = strlen(payload);
    pubmsg.qos = qos;//服务质量等级
    pubmsg.retained = retained;//保留主题的最后一条消息
    
    while(s_stMqttCtx.bConnected){
        MQTTClient_publishMessage(client, topic, &pubmsg, &token);
        LOGD("Waiting for up to %d seconds for publication of %s\n"
                "on topic %s for client with ClientID: %s\n",
                (int)(TIMEOUT/1000), payload, topic, s_stMqttCtx.azDeviceID);
        LOGD("Message with delivery token %d delivered\n", token);
        s32Ret = MQTTClient_waitForCompletion(client, token, TIMEOUT);
        break;
    }
    
    return HI_SUCCESS;
}
/* 订阅主题 */
HI_S32 PLUG_MQTT_SubClient(const HI_S8* topic, HI_S32 qos)
{
    HI_S32 s32Ret;
    
    //LOGI("Subscribing to topic %s\nfor client %s using QoS%d\n", topic, s_stMqttCtx.azDeviceID, qos);

    s32Ret = MQTTClient_subscribe(client, topic, qos);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("MQTTClient_subscribe error code:%d\n",s32Ret);
        return HI_FAILURE;
    }
    
    return HI_SUCCESS;
}

HI_S32 PLUG_MQTT_UnSubClient(const HI_S8* topic)
{
    HI_S32 s32Ret;
    
    LOGD("Subscribing to topic %s\nfor client %s using QoS%d\n", topic, s_stMqttCtx.azDeviceID);

    s32Ret = MQTTClient_unsubscribe(client, topic);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("MQTTClient_unsubscribe error code:%d\n",s32Ret);
        return HI_FAILURE;
    }
    
    return HI_SUCCESS;
}

HI_S32 PLUG_MQTT_Disconnect(HI_VOID)
{
    if (HI_TRUE == s_stMqttCtx.bConnected)
    {
        s_stMqttCtx.bConnected = HI_FALSE;
        MQTTClient_disconnect(client, 10000);
        MQTTClient_destroy(&client);
    }
    
    return HI_SUCCESS;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */

